#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>

using std::cout;
using std::endl;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 这里就将条件变量和锁定义为全局的，后面会使用init和destroy函数
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;   // 条件变量本身不是互斥的，所以要配和互斥锁来使用

int tickets = 1000;

void *start_routine(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (1)
    {
        pthread_mutex_lock(&lock);
        // if (tickets > 0)//判断暂时省略
        pthread_cond_wait(&cond, &lock); // 这里为什么要有lock锁，我们后面说
        cout << name << "->" << tickets << endl;
        cout.flush();
        tickets--;
        pthread_mutex_unlock(&lock);
    }
}
int main()
{

    pthread_t t[5];
    for (size_t i = 0; i < 5; ++i)
    {
        char *buffer = new char[128];
        snprintf(buffer, 128, "thread %d", i + 1);
        pthread_create(t + i, nullptr, start_routine, buffer);
        // pthread_create(&t[i], nullptr, start_routine, buffer);
    }
    while (1)
    {
        sleep(1);
        //pthread_cond_signal(&cond);
        pthread_cond_broadcast(&cond);
        cout << "main thread wakeup one thread..." << endl;
        cout.flush();
    }
    for (size_t i = 0; i < 5; ++i)
        pthread_join(t[i], nullptr);

    return 0;
}

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 这里就将条件变量和锁定义为全局的，后面会使用init和destroy函数
// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;   // 条件变量本身不是互斥的，所以要配和互斥锁来使用

// int tickets = 1000;

// void *start_routine(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     while (1)
//     {
//         pthread_mutex_lock(&lock);
//         // if (tickets > 0)//判断暂时省略
//         pthread_cond_wait(&cond, &lock); // 这里为什么要有lock锁，我们后面说
//         cout << name << "->" << tickets << endl;
//         cout.flush();
//         tickets--;
//         pthread_mutex_unlock(&lock);
//     }
// }
// int main()
// {
//     // 通过条件变量控制线程的执行
//     pthread_t t1, t2;
//     pthread_create(&t1, nullptr, start_routine, (void *)"thread 1");
//     pthread_create(&t2, nullptr, start_routine, (void *)"thread 2");
//     while (1)
//     {
//         sleep(1);
//         pthread_cond_signal(&cond);
//         cout << "main thread wakeup one thread..." << endl;
//         cout.flush();

//     }
//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);

//     return 0;
// }